package com.xinyin.aiqinhaiback.modbus;

import com.serotonin.modbus4j.BatchRead;
import com.serotonin.modbus4j.BatchResults;
import com.serotonin.modbus4j.ModbusMaster;
import com.serotonin.modbus4j.code.DataType;
import com.serotonin.modbus4j.exception.ErrorResponseException;
import com.serotonin.modbus4j.exception.ModbusInitException;
import com.serotonin.modbus4j.exception.ModbusTransportException;
import com.serotonin.modbus4j.locator.BaseLocator;
import com.xinyin.aiqinhaiback.Utils.ModbusAddressUtil;
import com.xinyin.aiqinhaiback.common.Enum.ResultEnum;
import com.xinyin.aiqinhaiback.exception.MyException;

import java.util.Set;

public  class ModbusClient {

	/**
	 * 获取master
	 *
	 * @return
	 * @throws ModbusInitException
	 */

	private ModbusMaster master=null;

	public ModbusClient(ModbusMaster master){
		//System.out.println(master);
		this.master=master;
	}

	public  ModbusMaster getMaster() throws ModbusInitException {
		return master;
	}

	/**
	 * 读取[01 Coil Status 0x]类型 开关数据
	 *
	 * @param slaveId
	 *            slaveId
	 * @param offset
	 *            位置
	 * @return 读取值
	 * @throws ModbusTransportException
	 *             异常
	 * @throws ErrorResponseException
	 *             异常
	 * @throws ModbusInitException
	 *             异常
	 */
	public  Boolean readCoilStatus(int slaveId, int offset)
			throws ModbusTransportException, ErrorResponseException, ModbusInitException {
		// 01 Coil Status
		BaseLocator<Boolean> loc = BaseLocator.coilStatus(slaveId, offset);
		Boolean value = getMaster().getValue(loc);
		return value;
	}

	/**
	 * 读取[02 Input Status 1x]类型 开关数据
	 *
	 * @param slaveId
	 * @param offset
	 * @return
	 * @throws ModbusTransportException
	 * @throws ErrorResponseException
	 * @throws ModbusInitException
	 */
	public  Boolean readInputStatus(int slaveId, int offset)
			throws ModbusTransportException, ErrorResponseException, ModbusInitException {
		// 02 Input Status
		BaseLocator<Boolean> loc = BaseLocator.inputStatus(slaveId, offset);
		Boolean value = getMaster().getValue(loc);
		return value;
	}

	/**
	 * 读取[03 Holding Register类型 2x]模拟量数据
	 *
	 * @param slaveId
	 *            slave Id
	 * @param offset
	 *            位置
	 * @param dataType
	 *            数据类型,来自com.serotonin.modbus4j.code.DataType
	 * @return
	 * @throws ModbusTransportException
	 *             异常
	 * @throws ErrorResponseException
	 *             异常
	 * @throws ModbusInitException
	 *             异常
	 */
	public  Number readHoldingRegister(int slaveId, int offset, int dataType)
			throws ModbusTransportException, ErrorResponseException, ModbusInitException {
		// 03 Holding Register类型数据读取
		BaseLocator<Number> loc = BaseLocator.holdingRegister(slaveId, offset, dataType);
		Number value = getMaster().getValue(loc);
		return value;
	}

	/**
	 * 读取[04 Input Registers 3x]类型 模拟量数据
	 *
	 * @param slaveId
	 *            slaveId
	 * @param offset
	 *            位置
	 * @param dataType
	 *            数据类型,来自com.serotonin.modbus4j.code.DataType
	 * @return 返回结果
	 * @throws ModbusTransportException
	 *             异常
	 * @throws ErrorResponseException
	 *             异常
	 * @throws ModbusInitException
	 *             异常
	 */
	public  Number readInputRegisters(int slaveId, int offset, int dataType)
			throws ModbusTransportException, ErrorResponseException, ModbusInitException {
		// 04 Input Registers类型数据读取
		BaseLocator<Number> loc = BaseLocator.inputRegister(slaveId, offset, dataType);
		Number value = getMaster().getValue(loc);
		return value;
	}

	/**
	 * 批量读取使用方法
	 *
	 * @throws ModbusTransportException
	 * @throws ErrorResponseException
	 * @throws ModbusInitException
	 */


	public BatchResults<Integer> batchRead(Set<Integer> list) throws ModbusTransportException, ErrorResponseException, ModbusInitException {
		BatchResults<Integer> results;
		try {
			BatchRead<Integer> batch = new BatchRead<Integer>();

			for(Integer port :list){
				if (ModbusAddressUtil.getFunctionCode(port)==1){
					batch.addLocator(port, BaseLocator.coilStatus(1, ModbusAddressUtil.getOffset(port)-1));
				}

				if (ModbusAddressUtil.getFunctionCode(port)==2){
					batch.addLocator(port, BaseLocator.inputStatus(1,  ModbusAddressUtil.getOffset(port)));
				}

				if (ModbusAddressUtil.getFunctionCode(port)==3){
					batch.addLocator(port, BaseLocator.holdingRegister(1, ModbusAddressUtil.getOffset(port), DataType.FOUR_BYTE_FLOAT));
				}

				if (ModbusAddressUtil.getFunctionCode(port)==4){
					batch.addLocator(port, BaseLocator.inputRegister(1, ModbusAddressUtil.getOffset(port)-1,DataType.FOUR_BYTE_FLOAT_SWAPPED));
				}

			}

			ModbusMaster master = getMaster();
			batch.setContiguousRequests(false);
			results = master.send(batch);
			//System.out.println(ip+results);
		}catch (Exception e) {
			System.err.println("error"+e.getMessage());
			throw new MyException(ResultEnum.COMMON_FAILED);

		}finally {
			//getMaster().destroy();
		}
		return results;
	}



//	public Object getData(Integer port) throws ModbusTransportException, ErrorResponseException, ModbusInitException {
//		Object obj=new Object();
//		try {
//
//
//			if (ModbusAddressUtil.getFunctionCode(port)==1){
//				obj=readInputStatus(1, ModbusAddressUtil.getOffset(port));
//			}
//
//			if (ModbusAddressUtil.getFunctionCode(port)==2){
//				obj=readInputStatus(1,  ModbusAddressUtil.getOffset(port));
//			}
//
//			if (ModbusAddressUtil.getFunctionCode(port)==3){
//				obj=readHoldingRegister(1,  ModbusAddressUtil.getOffset(port), DataType.FOUR_BYTE_FLOAT);
//			}
//
//			if (ModbusAddressUtil.getFunctionCode(port)==4){
//				obj= readInputRegisters(1,  ModbusAddressUtil.getOffset(port), DataType.FOUR_BYTE_FLOAT);//
//			}
//		}catch (Exception e){
//			System.out.println(port+"error"+e.getMessage());
//		}
//		return obj;
//	}
	/**
	 * 测试
	 *
	 * @param args
	 */
	public  void main(String[] args) {
		try {
			// 01测试
			Boolean v011 = readCoilStatus(1, 0);
			Boolean v012 = readCoilStatus(1, 1);
			Boolean v013 = readCoilStatus(1, 6);
			System.out.println("v011:" + v011);
			System.out.println("v012:" + v012);
			System.out.println("v013:" + v013);
			// 02测试
			Boolean v021 = readInputStatus(1, 0);
			Boolean v022 = readInputStatus(1, 1);
			Boolean v023 = readInputStatus(1, 2);
			System.out.println("v021:" + v021);
			System.out.println("v022:" + v022);
			System.out.println("v023:" + v023);

			// 03测试
			Number v031 = readHoldingRegister(1, 1, DataType.FOUR_BYTE_FLOAT);// 注意,float
			Number v032 = readHoldingRegister(1, 3, DataType.FOUR_BYTE_FLOAT);// 同上
			System.out.println("v031:" + v031);
			System.out.println("v032:" + v032);

			// 04测试
			Number v041 = readInputRegisters(1, 0, DataType.FOUR_BYTE_FLOAT);//
			Number v042 = readInputRegisters(1, 2, DataType.FOUR_BYTE_FLOAT);//
			System.out.println("v041:" + v041);
			System.out.println("v042:" + v042);
			// 批量读取
			//  batchRead();

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}
